package clients

import (
	"errors"
	"strconv"
	"strings"
	"sync"
	"time"

	log "gitee.com/sansaniot/ssiot-core/logger"
	toolsDB "gitee.com/sansaniot/ssiot-core/storage/database/dbconfig"
	. "gitee.com/sansaniot/ssiot-core/storage/database/gorm/logger"
	"gorm.io/driver/mysql"
	"gorm.io/driver/postgres"
	"gorm.io/driver/sqlite"
	"gorm.io/driver/sqlserver"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"

	"ssforward/common/constant"
	"ssforward/common/enums"
	"ssforward/common/utils"
	"ssforward/internal/forward/models"
)

var ForwardDbClients sync.Map

// 开放的数据库类型
var opens = map[string]func(string) gorm.Dialector{
	enums.DriverOfMysql.Get().Name:     mysql.Open,
	enums.DriverOfPostgres.Get().Name:  postgres.Open,
	enums.DriverOfSqlserver.Get().Name: sqlserver.Open,
	enums.DriverOfSqlite.Get().Name:    sqlite.Open,
}

func InitDbClientList(serverList []models.SysForwardServer) {
	for i := range serverList {
		go func(serverItem models.SysForwardServer) {
			_ = InitDbClientItem(serverItem)
		}(serverList[i])
	}
}

func InitDbClientItem(serverItem models.SysForwardServer) error {
	dbPoint, err := instanceServerDbClient(serverItem)
	if err != nil {
		log.Errorf("[%+v],当前db转发服务配置信息=[%+v]", err.Error(), serverItem)
		return err
	}
	//缓存当前客户端对象
	clientId := enums.Database.Get().Value + "-" + serverItem.Id
	ForwardDbClients.Store(clientId, dbPoint)
	log.Infof("转发db连接成功 clientId=[%+v]", clientId)
	return nil
}

// 删除数据库连接
func RemoveDbClientItem(clientId string) {
	if dbPoint, ok := ForwardDbClients.Load(clientId); ok {
		//断开原始连接
		if dbPoint != nil {
			if sqlDb, err := dbPoint.(*gorm.DB).DB(); err == nil {
				_ = sqlDb.Close()
			}
			dbPoint = nil
		}
		//移除缓存
		ForwardDbClients.Delete(clientId)
		log.Infof("断开转发db连接,并删除缓存 clientId=[%+v]", clientId)
	}
}

func instanceServerDbClient(serverItem models.SysForwardServer) (*gorm.DB, error) {
	// 驱动类型
	driver := serverItem.DbDriver
	driverType := enums.GetDriverType(driver)
	if len(driverType.Name) == 0 {
		return nil, errors.New("数据驱动不被支持" + driver)
	}
	// 连接url
	source := driverType.SourceFmt
	pwd, ee := utils.AesDecrypt(serverItem.Password, constant.SALTKEY)
	if ee != nil {
		return nil, errors.New("解密数据库密码失败")
	}
	source = strings.ReplaceAll(source, "#username", serverItem.Username)
	source = strings.ReplaceAll(source, "#password", pwd)
	source = strings.ReplaceAll(source, "#host", serverItem.Host)
	source = strings.ReplaceAll(source, "#port", strconv.Itoa(serverItem.Port))
	source = strings.ReplaceAll(source, "#dbname", serverItem.DbName)
	// 初始化连接
	registers := make([]toolsDB.ResolverConfigure, 0)
	resolverConfig := toolsDB.NewConfigure(source, 5, 50, 120, 600, registers)
	db, err := resolverConfig.Init(&gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true,
		},
		Logger: New(
			logger.Config{
				SlowThreshold: time.Second,
				Colorful:      true,
				LogLevel: logger.LogLevel(
					log.DefaultLogger.Options().Level.LevelForGorm()),
			},
		),
	}, opens[driver])
	if err != nil {
		log.Error("转发db连接创建失败" + err.Error())
		return nil, errors.New("db连接创建失败: " + err.Error())
	}
	return db, nil
}

// 测试连接
func TestDbClientItem(serverItem models.SysForwardServer) (err error) {
	clientId := enums.Database.Get().Value + "-" + serverItem.Id
	if dbPoint, ok := ForwardDbClients.Load(clientId); ok && dbPoint != nil {
		_, err = dbPoint.(*gorm.DB).DB()
	} else {
		err = InitDbClientItem(serverItem)
	}
	return
}
